﻿using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Imaging;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Configuration;
using Microsoft.Http;
using Microsoft;
using Newtonsoft.Json;
using System.Threading;
using System.Net;
using System.Net.Mail;
using System.Net.Sockets;
using System.IO;
using System.Globalization;
using System.Text.RegularExpressions;
using Twilio;

namespace ShelSystemViewer
{
    public partial class StatusViewerForm : Form
    {
        #region Private fields
        private static readonly String PlayerDetailsBoxText = "Player Details ";
        private static readonly String PlayerNameLabelText = "Name: ";
        private static readonly String PlayerDobLabelText = "D.O.B.: ";
        private static readonly String PlayerAddressLabelText = "Address: ";
        private static readonly String PlayerPhoneLabelText = "Phone #: ";
        private static readonly String PlayerHeightLabelText = "Height: ";
        private static readonly String PlayerWeightLabelText = "Weight: ";
        private static readonly String ParentPhoneLabelText = "Parent's Phone #: ";
        private static readonly String ParentAltPhoneLabelText = "Parent's Alt. Phone #: ";
        private static readonly String ParentNamesLabelText = "Parent's Names: ";
        private static readonly String DocPhoneLabelText = "Doctor's Phone #: ";
        private static readonly String DocNameLabelText = "Doctor's Name: ";
        private static readonly String HitNumLabelText = "Number of Hits: ";
        private static readonly String AvgHitSeverityLabelText = "Average Hit Severity: ";
        private static readonly String AvgTempLabelText = "Average Temperature: ";
        private static readonly String TraumaConsciousLabelText = "Was Player Conscious? ";
        private static readonly String TraumaTimeLabelText = "Time: ";
        private static readonly String TraumaSeverityLabelText = "Severity: ";
        private static readonly String DefaultTraumaHitNumToDisplay = "10";

        // Display formatting
        private static readonly Point buttonStart = new Point(50, 100);
        private static readonly Point buttonLargeDim = new Point(150, 150);
        private static readonly Point buttonSmallDim = new Point(100, 100);
        private static readonly int buttonSpacing = 20;
        private static readonly float buttonImageRatio = 0.8f;

        // New Player form
        PlayerUpdateForm playerUpdateForm;

        // Last player info whose details were displayed
        private static String CurrPlayerId;
        private static Player CurrPlayer;
        private static Contact DoctorInfo;
        private static Contact Parent1Info;
        private static Contact Parent2Info;
        System.Threading.Thread streamThread;

        private static String WebServiceUrlKey = "WebServiceUrl";

        // Player dataset
        private static List<Player> players;
        private static List<Button> playerButtons;

        // Add player button
        private static Button addPlayerButton;

        // Thread-safety locks
        private static readonly object playerLock = new object();
        private static readonly object playerButtonLock = new object();

        // Delegate for creating new buttons on the main form
        private delegate void AddPlayerButtonDel();
        private delegate void UpdatePlayerButtonsDel();
        private delegate void RemovePlayerButtonDel();

        // Constants for displaying historical data
        private static readonly DateTime Today = DateTime.Today;
        private static readonly int DaysInWeek = 7;

        // Constants for displaying current game data
        private static readonly int MaxNumOfPointsToDisplay = 30;

        // Twilio sandbox SMS account information
        private static readonly String SmsAccountPhoneNumber = "+1 415-599-2671";
        private static readonly String SmsAccountSid = "ACcfd49a418913492fba9705cd2d9e399f";
        private static readonly String SmsAccountNumberAuthToken = "caa8d563d6fb696cea42332c843fb1e5";   

        #endregion 

        // Constructor
        public StatusViewerForm()
        {
            InitializeComponent();
           
            // configure what actions should be performed when each button is clicked
            HideButton.Click += new EventHandler(HidePlayerDetails);
            EditButton.Click += new EventHandler(PerformActionForPlayerDetails);
            RefreshBtn.Click += new EventHandler(RefreshPlayerDetails);
            Resize += new EventHandler(RearrangeComponents);
            HistStatsStartDatePicker.ValueChanged += new EventHandler(SetEndDate);
            HistStatsFilterButton.Click += new EventHandler(DetermineHistoricalStatsChartToDisplay);
            HistStatsSwitchChartsBtn.Click += new EventHandler(SwitchHistoricalStatsChartDisplayInfo);
            SendTextBtn.Click += new EventHandler(SendDoctorTextMessage);

            // to start with, make the window the size of their screen's current working area
            DesktopLocation = System.Windows.Forms.Screen.PrimaryScreen.WorkingArea.Location;
            Location = System.Windows.Forms.Screen.PrimaryScreen.WorkingArea.Location;
            Size = System.Windows.Forms.Screen.PrimaryScreen.WorkingArea.Size;

            // Reset date to always be today - format: Saturday, October 10 - Red vs. Blue
            labelGameTime.Text = DateTime.Now.ToString("dddd, MMMM dd '-- Red vs. Blue'", 
                CultureInfo.InvariantCulture);
            ResetDefaultHistoricalStatsDates();
            
            // Add new player button
            addPlayerButton = new Button();
            addPlayerButton.Click += new System.EventHandler(DisplayNewPlayerForm);
            addPlayerButton.FlatAppearance.BorderColor = Color.Black;
            addPlayerButton.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
            addPlayerButton.Font = new Font("Microsoft Sans Serif", 15.75F, FontStyle.Regular, GraphicsUnit.Point, ((byte)(0)));
            addPlayerButton.Image = global::ShelSystemViewer.Properties.Resources.grey_helmet;
            addPlayerButton.Location = new Point(12, 599);
            addPlayerButton.Name = "AddPlayerButton";
            addPlayerButton.Size = new Size(291, 275);
            addPlayerButton.TabIndex = 1;
            addPlayerButton.Text = "Add New Player";
            addPlayerButton.TextAlign = ContentAlignment.BottomCenter;
            addPlayerButton.UseVisualStyleBackColor = true;
            addPlayerButton.Visible = false;
            this.Controls.Add(addPlayerButton);
            

            // callback for updating the main menu
            backgroundWorker.RunWorkerAsync();

            // Initialize the player list
            players = new List<Player>();
            playerButtons = new List<Button>();

            playerUpdateForm = new PlayerUpdateForm(ConfigurationManager.AppSettings[WebServiceUrlKey]);
            playerUpdateForm.Hide();
        }

        // Destructor
        ~StatusViewerForm()
        {
        }

        // Shrink the main page and instead show Player Details page
        private void DisplayPlayerDetails(object sender, EventArgs e)
        {
            try
            {
                // spin off a separate thread to stream live data
                streamThread = new System.Threading.Thread(HandleStreamingData);
                streamThread.Start();

                ResetPlayerDetailsLabels();
                Button senderButton = (Button)sender;
                // Base player id off of the number on the button's name, rather than the uniform number
                CurrPlayerId = senderButton.Name.ToString().Remove(0, 10).Trim();
                CurrPlayer = null;
                DoctorInfo = null;
                Parent1Info = null;
                Parent2Info = null;

                if (PopulatePlayerInformation())
                {
                    var client = new HttpClient();
                    PopulatePlayerContactsInformation(client, CurrPlayer.UniformNum);
                    PopulateCurrentGameTabInformation(client);
                    PopulateHistStatsTabInformation();
                }
                PlayerDetailBox.Visible = true;
            }
            catch (SystemException exception)
            {
                Console.WriteLine("Error: " + exception.Message);
            }
        }

        // Open connection to streaming data & display data in current game chart
        private void HandleStreamingData(Object stateInfo)
        {
            try
            {
                var client = new StreamClient();
                foreach (var rawMessage in client.Connect())
                {                    
                    Invoke((MethodInvoker)delegate
                    {
						CurrentGameChart.Visible = true;
                        // keep only the last X data points on the chart...remove oldest if necessary
                        if (CurrentGameChart.Series[0].Points.Count >= MaxNumOfPointsToDisplay)
                        {
                            CurrentGameChart.Series[0].Points.RemoveAt(0);
                        }
                        if (CurrentGameChart.Series[1].Points.Count >= MaxNumOfPointsToDisplay)
                        {
                            CurrentGameChart.Series[1].Points.RemoveAt(0);
                        }

                        // Traumatic hit
                        if (rawMessage.Contains("trauma"))
                        {
                            var hit = JsonConvert.DeserializeObject<TraumaHit>(rawMessage);

                            // update most recent traumatic hit info
                            if (hit != null)
                            {
                                RecentTraumaTimeLabel.Text += hit.HitDateTime;
                                RecentTraumaSeverityLabel.Text += hit.Severity;
                                RecentTraumaConsciousLabel.Text += (hit.WasPlayerConscious ? "yes" : "no");
                            }
                        }
                        // Regular statistic
                        else
                        {
                            var stat = JsonConvert.DeserializeObject<Statistics>(rawMessage);

                            // add new point to current game chart
                            if (stat != null)
                            {
                                CurrentGameChart.Series[0].Points.AddXY(stat.DataDateTime.ToLongTimeString(), stat.Severity);
                                CurrentGameChart.Series[1].Points.AddXY(stat.DataDateTime.ToLongTimeString(), stat.Temperature);
                            }
                        }
                    });
                }
            }
            catch (Exception exception)
            {
					Console.WriteLine("Error when retrieving/parsing streaming sensor information: " + exception.Message);
            }
        }

        // Populate player's personal information
        public bool PopulatePlayerInformation()
        {
            var success = true;
            var client = new HttpClient();
            var query = ConfigurationManager.AppSettings[WebServiceUrlKey] + "/api/v1/player/" + CurrPlayerId;
            var rawResult = client.Get(query).Content.ReadAsString();

            try
            {
                CurrPlayer = (Player)JsonConvert.DeserializeObject(rawResult, typeof(Player));
                PlayerDetailBox.Text += " - #" + CurrPlayer.UniformNum;
                NameLabel.Text += CurrPlayer.FirstName + " " + CurrPlayer.LastName;
                DobLabel.Text += CurrPlayer.Birthday;
                AddressLabel.Text += CurrPlayer.Address;
                PhoneLabel.Text += CurrPlayer.PhoneNumber;
                HeightLabel.Text += CurrPlayer.Height + " ft";
                WeightLabel.Text += CurrPlayer.Weight + " lbs";
                DocNotesText.Text = CurrPlayer.DoctorNotes;
                MedHistoryText.Text = CurrPlayer.MedicalHistory;
            }
            catch (SystemException exception)
            {
                success = false;
                Console.WriteLine("Error when parsing player information from API: " + exception.Message);
            }

            return success;
        }

        // Populate player's current game tab information on Player Details page
        private void PopulateCurrentGameTabInformation(HttpClient client)
        {
            try
            {
                // set avg hit info
                var query = ConfigurationManager.AppSettings[WebServiceUrlKey] + "/api/v1/player/" + CurrPlayerId + "/history/1";
                var rawResult = client.Get(query).Content.ReadAsString();
                var playerStats = (List<Statistics>)JsonConvert.DeserializeObject(rawResult, typeof(List<Statistics>));
                if (playerStats.Count > 0 && playerStats[0].DataDateTime.Date == Today.Date)
                {
                    // set avg hit info
                    var todayStats = playerStats[0];
                    AvgTempLabel.Text += todayStats.Temperature;
                    AvgHitSeverityLabel.Text += todayStats.Severity;
                    HitNumLabel.Text += todayStats.TotalHitCount;
                }
                else
                {
                    HitNumLabel.Text += "No game is being played.";
                    AvgHitSeverityLabel.Text += "No game is being played.";
                    AvgTempLabel.Text += "No game is being played.";
                }

                // default recent trauma hit info
                RecentTraumaTimeLabel.Text += "n/a";
                RecentTraumaSeverityLabel.Text += "n/a";
                RecentTraumaConsciousLabel.Text += "n/a";
            }
            catch (SystemException exception)
            {
                Console.WriteLine("Error when parsing most recent hit statistics from API: " + exception.Message);
            }
        }

        // Populate player's historical statistics tab information on Player Details page
        private void PopulateHistStatsTabInformation()
        {
            try
            {
                // For historical data tab, display week's worth of data by default
                var startDate = Today.Date.Subtract(TimeSpan.FromDays(DaysInWeek - 1));
                var timeDesc = "Weekly Stats - "
                    + startDate.ToString("dddd, MMMM dd")
                    + " to " + Today.ToString("dddd, MMMM dd");
                HistStatsStartDatePicker.Value = startDate;
                HistStatsStartDatePicker.MaxDate = Today;

                DisplayDailyHistoricalDataOverview(startDate, DaysInWeek - 1, timeDesc);

                TraumaHitNumTxtBox.Text = DefaultTraumaHitNumToDisplay;
                DetermineHistoricalStatsTraumaNum();
            }
            catch (SystemException exception)
            {
                Console.WriteLine("Error when parsing historical statistics from API: " + exception.Message);
            }
        }

        // Populate player's doctor & parent information on Player Details page
        private void PopulatePlayerContactsInformation(HttpClient client, int uniformNum)
        {
            var query = ConfigurationManager.AppSettings[WebServiceUrlKey] + "/api/v1/player/" + CurrPlayerId + "/contacts";
            var rawResult = client.Get(query).Content.ReadAsString();
            try
            {
                var contact = (List<Contact>)JsonConvert.DeserializeObject(rawResult, typeof(List<Contact>));
                var foundPrimParent = false;
                contact.OrderBy(c => c.Id).ToList().ForEach(c =>
                {
                    c.AssociatedPlayerId = uniformNum;

                    // set doctor info
                    if (c.Relation == Relationship.Doctor)
                    {
                        DocNameLabel.Text += c.FirstName + " " + c.LastName;
                        DocPhoneLabel.Text += c.PhoneNumber;
                        DoctorInfo = c;
                    }
                    // set parent info
                    else if (c.Relation == Relationship.Mother || c.Relation == Relationship.Father)
                    {
                        if (!foundPrimParent)
                        {
                            ParentNamesLabel.Text += c.FirstName + " " + c.LastName;
                            ParentPhoneLabel.Text += c.PhoneNumber;
                            ParentAltPhoneLabel.Text += c.AltPhoneNumber;
                            Parent1Info = c;
                            foundPrimParent = true;
                        }
                        else
                        {
                            ParentNamesLabel.Text += ", " + c.FirstName + " " + c.LastName;
                            if (c.PhoneNumber.Length > 0
                                && ParentPhoneLabel.Text.Length <= ParentPhoneLabelText.Length)
                            {
                                ParentPhoneLabel.Text += c.PhoneNumber;
                            }
                            if (c.AltPhoneNumber.Length > 0
                                && ParentAltPhoneLabel.Text.Length <= ParentAltPhoneLabelText.Length)
                            {
                                ParentAltPhoneLabel.Text += c.AltPhoneNumber;
                            } 
                            Parent2Info = c;
                        }
                    }
                });
            }
            catch (SystemException exception)
            {
                Console.WriteLine("Error when parsing contact's information from API: " + exception.Message);
            }
        }

        // Reset start & end date for current game chart
        private void ResetDefaultHistoricalStatsDates()
        {
            HistStatsStartDatePicker.Value = Today.Date.Subtract(TimeSpan.FromDays(DaysInWeek - 1));
            HistStatsEndDatePicker.Value = Today.Date;
        }

        // New start date selected...update value of end date
        private void SetEndDate(object sender, EventArgs e)
        {
            HistStatsEndDatePicker.Value = HistStatsStartDatePicker.Value.AddDays(DaysInWeek - 1);
        }

        // switch the historical chart controls being displayed (filters and whatnot)
        private void SwitchHistoricalStatsChartDisplayInfo(object sender, EventArgs e)
        {
            // switch to hits-per-game overview chart
            if (HistChartComboBox.SelectedIndex == 0)
            {
                TraumaHitsToShowLabel.Visible = false;
                TraumaHitNumTxtBox.Visible = false;
                HistStatsTraumaChart.Visible = false;
                HistStatsStartDateLabel.Visible = true;
                HistStatsStartDatePicker.Visible = true;
                HistStatsEndDateLabel.Visible = true;
                HistStatsEndDatePicker.Visible = true;
                HistStatsOverviewChart.Visible = true;

                DetermineHistoricalStatsDateRange(null, null);
            }
            // switch to traumatic hit details
            else if (HistChartComboBox.SelectedIndex == 1)
            {
                HistStatsStartDateLabel.Visible = false;
                HistStatsStartDatePicker.Visible = false;
                HistStatsEndDateLabel.Visible = false;
                HistStatsEndDatePicker.Visible = false;
                HistStatsOverviewChart.Visible = false;
                TraumaHitsToShowLabel.Visible = true;
                TraumaHitNumTxtBox.Visible = true;
                HistStatsTraumaChart.Visible = true;
            }
        }

        // determine which historical chart to actually display
        private void DetermineHistoricalStatsChartToDisplay(object sender, EventArgs e)
        {
            // hits-per-game overview chart
            if (HistChartComboBox.SelectedIndex == 0)
            {
                DetermineHistoricalStatsDateRange(null, null);
            }
            // traumatic hit details
            else if (HistChartComboBox.SelectedIndex == 1)
            {
                DetermineHistoricalStatsTraumaNum();
            }
        }

        // User selected the date range, so get those #s to prepare for display
        private void DetermineHistoricalStatsDateRange(object sender, EventArgs e)
        {
            try
            {
                if (HistStatsStartDatePicker.Value > HistStatsEndDatePicker.Value)
                {
                    // invalid start & end date combination
                    System.Windows.Forms.MessageBox.Show(
                        "The start date must come before the end date.", "Error", MessageBoxButtons.OK);
                    ResetDefaultHistoricalStatsDates();
                }
                else
                {
                    DateTime startDate = HistStatsStartDatePicker.Value;
                    DateTime endDate = HistStatsEndDatePicker.Value;
                    string timeDesc = "Game Overview Stats for " + startDate.Date.ToString("dddd, MMMM dd") 
                        + " to " + endDate.ToString("dddd, MMMM dd");
                    int numOfDays = (endDate.Date - startDate.Date).Days;

                    DisplayDailyHistoricalDataOverview(startDate, numOfDays, timeDesc);
                }
            }
            catch (SystemException exception)
            {
                Console.WriteLine("Error: " + exception.Message);
            }
        }

        // Display historical data overview for the past X time frame (whatever time interval passed in)
        private void DisplayDailyHistoricalDataOverview(DateTime start, int numDaysToDisplay, string timeDescription)
        {
            HistStatsOverviewChart.Series[0].Points.Clear();
            HistStatsOverviewChart.Series[1].Points.Clear();
            HistStatsOverviewChart.Titles.Clear();

            var client = new HttpClient();
            try
            {
                var numDaysToRetrieve = (Today.Date - start.Date).Days + 1;
                var query = ConfigurationManager.AppSettings[WebServiceUrlKey]
                    + "/api/v1/player/" + CurrPlayerId + "/history/" + numDaysToRetrieve;
                var rawResult = client.Get(query).Content.ReadAsString();

                HistStatsOverviewChart.Titles.Add(timeDescription);
                var playerStats = (List<Statistics>)JsonConvert.DeserializeObject(rawResult, typeof(List<Statistics>));

                // pull out only the stats for the past hitNum & group them by date
                DateTime end = start.AddDays(numDaysToDisplay);
                var statsForTimeInterval = playerStats.Where(s => end.Subtract(s.DataDateTime).Days 
                    <= numDaysToDisplay).ToList();

                // for each day, add point to chart
                while (start.Date <= end.Date)
                {
                    // pull hit records for current day from list
                    var statsForDay = statsForTimeInterval.Where(s 
                        => s.DataDateTime.Date.Equals(start.Date));

                    var currIndex = HistStatsOverviewChart.Series[0].Points.Count();

                    if (statsForDay.Count() > 0)
                    {
                        // add point for this date & the # of total hits that day
                        var dailyHitCount = statsForDay.Sum(s => s.TotalHitCount);
                        HistStatsOverviewChart.Series[0].Points.AddXY(start.Date, dailyHitCount);
                        Decimal avgTemp = statsForDay.Sum(s => s.Temperature)/statsForDay.Count();
                        HistStatsOverviewChart.Series[1].Points.AddXY(start.Date, avgTemp);

                        // color the bar based on player's status
                        var avgStatus = statsForDay.Sum(s => Convert.ToInt16(s.PlayerStatus) * s.TotalHitCount) 
                            / statsForDay.Sum(s => s.TotalHitCount);
                        var maxStatus = statsForDay.Max(s => Convert.ToInt16(s.PlayerStatus));
                        if (maxStatus == Convert.ToInt16(Status.Emergency) 
                            || avgStatus >= Convert.ToInt16(Status.Emergency))
                        {
                            HistStatsOverviewChart.Series[0].Points[currIndex].Color = Color.Red;
                        }
                        else if (maxStatus == Convert.ToInt16(Status.Warning)
                            || avgStatus >= Convert.ToInt16(Status.Warning))
                        {
                            HistStatsOverviewChart.Series[0].Points[currIndex].Color = Color.Yellow;
                        }
                        else
                        {
                            HistStatsOverviewChart.Series[0].Points[currIndex].Color = Color.Lime;
                        }
                    }
                    else
                    {
                        // we want to add a point so this date shows up on the graph, but we don't want points to actually be drawn
                        HistStatsOverviewChart.Series[0].Points.AddXY(start.Date, 0);
                        HistStatsOverviewChart.Series[0].Points[currIndex].Color = Color.Transparent;
                        HistStatsOverviewChart.Series[1].Points.AddXY(start.Date, 0);
                        HistStatsOverviewChart.Series[1].Points[currIndex].MarkerColor = Color.Transparent;
                    }

                    // move to next day
                    start = start.AddDays(1);
                };
            }
            catch (SystemException exception)
            {
                Console.WriteLine("Error when parsing historical avg hit data from API: " + exception.Message);
            }
        }

        // User chose # of trauma hits, so get that # to prepare for display
        private void DetermineHistoricalStatsTraumaNum()
        {
            try
            {
                String input = TraumaHitNumTxtBox.Text;
                Regex NumberRegex = new Regex(@"^[0-9]*$");
                Match match = NumberRegex.Match(input);

                // validate input
                if (input == String.Empty)
                {
                    // empty input
                    System.Windows.Forms.MessageBox.Show(
                        "You must fill in the number of trauma hits to display.", "Error", MessageBoxButtons.OK);
                    TraumaHitNumTxtBox.Text = "10";
                }
                else if (!match.Success)
                {
                    // invalid number
                    System.Windows.Forms.MessageBox.Show(
                        "The trauma hit number must be a valid integer.", "Error", MessageBoxButtons.OK);
                }
                else
                {
                    // successful input
                    int hits = Convert.ToInt32(input);
                    string chartDesc = "Hit Details for the " + input + " Most Recent Traumatic Hits";

                    DisplayHistoricalTraumaData(hits, chartDesc);
                }
            }
            catch (SystemException exception)
            {
                Console.WriteLine("Error: " + exception.Message);
            }
        }

        // Display the past X traumatic hits (whatever X passed in)
        private void DisplayHistoricalTraumaData(int hitNum, string chartDescription)
        {
            HistStatsTraumaChart.Series[0].Points.Clear();
            HistStatsTraumaChart.Titles.Clear();

            var client = new HttpClient();
            try
            {
                var query = ConfigurationManager.AppSettings[WebServiceUrlKey]
                    + "/api/v1/player/" + CurrPlayerId + "/trauma/" + hitNum;
                var rawResult = client.Get(query).Content.ReadAsString();

                HistStatsTraumaChart.Titles.Add(chartDescription);
                var hits = (List<TraumaHit>)JsonConvert.DeserializeObject(rawResult, typeof(List<TraumaHit>));

                // for each hit, add point to chart
                int currIndex = 0;
                hits.OrderBy(h => h.HitDateTime).ToList().ForEach(h =>
                    {
                        // add point for this date
                        HistStatsTraumaChart.Series[0].Points.AddXY(h.HitDateTime.ToString(), h.Severity);

                        // color the bar based on player's consciousness status
                        if (h.WasPlayerConscious)
                        {
                            HistStatsTraumaChart.Series[0].Points[currIndex++].Color = Color.Lime;
                        }
                        else
                        {
                            HistStatsTraumaChart.Series[0].Points[currIndex++].Color = Color.Red;
                        }
                    });
            }
            catch (SystemException exception)
            {
                Console.WriteLine("Error when parsing historical trauma data from API: " + exception.Message);
            }
        }

        // Hide the Player Details page from showing & return to main page showing player's statuses
        private void HidePlayerDetails(object sender, EventArgs e)
        {
            PlayerDetailBox.Visible = false;
            ResetMainComponents();
        }

        // Perform some action for player information (either save changes or allow user to edit info)
        private void PerformActionForPlayerDetails(object sender, EventArgs e)
        {
            if (playerUpdateForm.IsDisposed)
            {
                playerUpdateForm = new PlayerUpdateForm(ConfigurationManager.AppSettings[WebServiceUrlKey]);
            }
            playerUpdateForm.SetUpdateFormType(false, CurrPlayer, DoctorInfo, Parent1Info, Parent2Info);
            playerUpdateForm.Show();
        }

        // Perform some action for player information (either save changes or allow user to edit info)
        private void RefreshPlayerDetails(object sender, EventArgs e)
        {
            ResetPlayerDetailsLabels();
            PopulatePlayerInformation();
            PopulatePlayerContactsInformation(new HttpClient(), CurrPlayer.UniformNum);
        }

        // Reset all the labels to default info for Player Details page
        private void ResetPlayerDetailsLabels()
        {
            PlayerDetailBox.Text = PlayerDetailsBoxText;
            NameLabel.Text = PlayerNameLabelText;
            DobLabel.Text = PlayerDobLabelText;
            AddressLabel.Text = PlayerAddressLabelText;
            PhoneLabel.Text = PlayerPhoneLabelText;
            HeightLabel.Text = PlayerHeightLabelText;
            WeightLabel.Text = PlayerWeightLabelText;
            ParentPhoneLabel.Text = ParentPhoneLabelText;
            ParentAltPhoneLabel.Text = ParentAltPhoneLabelText;
            ParentNamesLabel.Text = ParentNamesLabelText;
            DocPhoneLabel.Text = DocPhoneLabelText;
            DocNameLabel.Text = DocNameLabelText;

            HitNumLabel.Text = HitNumLabelText;
            AvgTempLabel.Text = AvgTempLabelText;
            AvgHitSeverityLabel.Text = AvgHitSeverityLabelText;
            RecentTraumaConsciousLabel.Text = TraumaConsciousLabelText;
            RecentTraumaTimeLabel.Text = TraumaTimeLabelText;
            RecentTraumaSeverityLabel.Text = TraumaSeverityLabelText;
        }

        /// <summary>
        /// Details specified by the user to re-arrange the components 
        /// on the screen, depending on size of screen
        /// </summary>
        private void RearrangeComponents(object sender, EventArgs e)
        {
            int xOffset = 20;
            int yOffset = 25;
            ResetPlayerDetailBoxComponents(xOffset, yOffset);
            ResetCurrentGameTabComponents(xOffset,
                DocNotesBox.Location.Y + DocNotesBox.Height + yOffset);
            ResetHistoricalInfoTabComponents(yOffset);
            ResetMainComponents();
        }

        // Reset the layout of the components in the Current Game tab section
        private void ResetCurrentGameTabComponents(int xOffset, int yOffset)
        {
            DetailsTabControl.Size = new Size(
                PlayerDetailBox.Width, PlayerDetailBox.Height - yOffset);
            DetailsTabControl.Location = new Point(
                xOffset / 2, yOffset);
            CurrentGameTab.Size = new Size(DetailsTabControl.Width, DetailsTabControl.Height - 30);
            GameHistoryTab.Size = CurrentGameTab.Size;

            yOffset = 30;
            HitNumLabel.Size = new Size(
                (DetailsTabControl.Width - xOffset) / 2, yOffset);
            RecentTraumaLabel.Size = HitNumLabel.Size;
            RecentTraumaTimeLabel.Size = HitNumLabel.Size;
            RecentTraumaSeverityLabel.Size = HitNumLabel.Size;
            RecentTraumaConsciousLabel.Size = HitNumLabel.Size;
            AvgHitSeverityLabel.Size = HitNumLabel.Size;
            AvgTempLabel.Size = HitNumLabel.Size;

            HitNumLabel.Text = HitNumLabelText;
            RecentTraumaTimeLabel.Text = TraumaTimeLabelText;
            RecentTraumaSeverityLabel.Text = TraumaSeverityLabelText;

            var chartHeight = CurrentGameChart.Location.Y + CurrentGameChart.Height;
            // column 1
            HitNumLabel.Location = new Point(
                xOffset / 2, CurrentGameTab.Height - yOffset * 3);
            AvgHitSeverityLabel.Location = new Point(
                xOffset / 2, CurrentGameTab.Height - yOffset * 2);
            AvgTempLabel.Location = new Point(
                xOffset / 2, CurrentGameTab.Height - yOffset);
            // column 2
            RecentTraumaLabel.Location = new Point(
                xOffset / 2 + DetailsTabControl.Width / 2,
                CurrentGameTab.Height - yOffset * 4);
            RecentTraumaTimeLabel.Location = new Point(
                xOffset / 2 + DetailsTabControl.Width / 2 + xOffset,
                CurrentGameTab.Height - yOffset * 3);
            RecentTraumaSeverityLabel.Location = new Point(
                xOffset / 2 + DetailsTabControl.Width / 2 + xOffset,
                CurrentGameTab.Height - yOffset * 2);
            RecentTraumaConsciousLabel.Location = new Point(
                xOffset / 2 + DetailsTabControl.Width / 2 + xOffset,
                CurrentGameTab.Height - yOffset);

            ResetCurrentGameChart((int)(CurrentGameTab.Width - 20),
                (int)(HitNumLabel.Location.Y - yOffset));
        }

        // Reset the layout of the components in the Current Game tab section
        private void ResetHistoricalInfoTabComponents(int offset)
        {
            HistChartComboBox.Location = SendTextBtn.Location;
            HistChartComboBox.SelectedIndex = 0;
            HistChartComboBox.Focus();
            HistStatsSwitchChartsBtn.Location = new Point(
                HistChartComboBox.Location.X + HistChartComboBox.Width + offset,
                HistChartComboBox.Location.Y);

            HistStatsOverviewChart.Size = CurrentGameChart.Size;
            HistStatsOverviewChart.Location = CurrentGameChart.Location;
            HistStatsStartDateLabel.Location = HitNumLabel.Location;
            HistStatsStartDatePicker.Location = new Point(
                HitNumLabel.Location.X + HistStatsStartDatePicker.Width, HitNumLabel.Location.Y);
            HistStatsEndDateLabel.Location = new Point(
                HistStatsStartDatePicker.Location.X + HistStatsStartDatePicker.Width + offset,
                HistStatsStartDatePicker.Location.Y);
            HistStatsEndDatePicker.Location = new Point(
                HistStatsEndDateLabel.Location.X + HistStatsEndDateLabel.Width,
                HistStatsEndDateLabel.Location.Y);

            HistStatsTraumaChart.Size = HistStatsOverviewChart.Size;
            HistStatsTraumaChart.Location = HistStatsOverviewChart.Location;
            HistStatsTraumaChart.Visible = false;
            TraumaHitsToShowLabel.Location = HistStatsStartDateLabel.Location;
            TraumaHitNumTxtBox.Location = new Point(
                TraumaHitsToShowLabel.Location.X + TraumaHitsToShowLabel.Width + offset, 
                TraumaHitsToShowLabel.Location.Y);
            TraumaHitsToShowLabel.Visible = false;
            TraumaHitNumTxtBox.Visible = false;

            HistStatsFilterButton.Location = new Point(
                HistStatsEndDatePicker.Location.X + HistStatsEndDatePicker.Width + offset,
                HistStatsEndDatePicker.Location.Y);
        }

        // Reset the layout of the chart in the Current Game tab section
        private void ResetCurrentGameChart(int xOffset, int yOffset)
        {
            if (yOffset > 0 && xOffset > 0)
            {
                SendTextBtn.Location = new Point(10,
                    (HitNumLabel.Location.Y - yOffset) / 2);

                CurrentGameChart.Size = new Size(xOffset,
                    yOffset - SendTextBtn.Height - 10);
                CurrentGameChart.Location = new Point(SendTextBtn.Location.X,
                    SendTextBtn.Location.Y + SendTextBtn.Height + 10);
            }
        }

        // Adds a new button to the playerButtons list
        private void CreatePlayerButton(Player player)
        {
            Button newButton = new Button();

            newButton.Click += new System.EventHandler(DisplayPlayerDetails);
            newButton.FlatAppearance.BorderColor = Color.Black;
            newButton.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
            newButton.Font = new Font("Microsoft Sans Serif", 15.75F, FontStyle.Regular, GraphicsUnit.Point, ((byte)(0)));
            newButton.Image = global::ShelSystemViewer.Properties.Resources.grey_helmet;
            newButton.Location = new Point(12, 110);
            newButton.Name = "PlayerIcon" + player.SensorId.ToString();
            newButton.Size = new Size(291, 275);
            newButton.TabIndex = 1;
            newButton.Text = "#" + player.UniformNum.ToString();
            newButton.TextAlign = ContentAlignment.BottomCenter;
            newButton.UseVisualStyleBackColor = true;
            newButton.Visible = true;

            playerButtons.Add(newButton);
        }

        private void AddPlayerButton()
        {
            if (playerButtons != null)
            {
                Controls.Add(playerButtons.Last());
            }
        }

        private void RemovePlayerButton()
        {
            if (playerButtons != null)
            {
                Controls.Remove(playerButtons.Last());
            }
        }

        // Reset the layout of the components in the Main section
        private void ResetMainComponents()
        {
            // Common
            panelTopBar.Location = new Point(0, 0);
            panelTopBar.Width = Size.Width;

            Point buttonPos = buttonStart;

            // Player buttons
            if (playerButtons != null)
            {
                lock (playerButtonLock)
                {
                    foreach (Button button in playerButtons)
                    {
                        button.Location = buttonPos;

                        // Resize based on whether or not the player detail box is displayed
                        if (!PlayerDetailBox.Visible)
                        {
                            button.Image = ResizeImage(button.Image, (int)((float)buttonLargeDim.X * buttonImageRatio), (int)((float)buttonLargeDim.Y * buttonImageRatio));
                            button.Width = buttonLargeDim.X;
                            button.Height = buttonLargeDim.Y;
                            button.Font = new Font("Microsoft Sans Serif", 15.75F, FontStyle.Regular, GraphicsUnit.Point, ((byte)(0)));
                        }
                        else
                        {
                            button.Image = ResizeImage(button.Image, (int)((float)buttonSmallDim.X * buttonImageRatio), (int)((float)buttonSmallDim.Y * buttonImageRatio));
                            button.Width = buttonSmallDim.X;
                            button.Height = buttonSmallDim.Y;
                            button.Font = new Font("Microsoft Sans Serif", 9.0F, FontStyle.Regular, GraphicsUnit.Point, ((byte)(0)));
                        }

                        // Increment for next button
                        buttonPos.X += button.Width + buttonSpacing;

                        // Determine when to wrap buttons to the next line based on whether the detail box is displayed or not
                        if (PlayerDetailBox.Visible)
                        {
                            if (buttonPos.X > (Size.Width - PlayerDetailBox.Size.Width - button.Width - buttonSpacing))
                            {
                                buttonPos.X = buttonStart.X;
                                buttonPos.Y += button.Height + buttonSpacing;
                            }
                        }
                        else
                        {
                            if (buttonPos.X > (Size.Width - button.Width - buttonSpacing))
                            {
                                buttonPos.X = buttonStart.X;
                                buttonPos.Y += button.Height + buttonSpacing;
                            }
                        }
                    }
                }
            }

            // AddPlayer button
            if (addPlayerButton != null)
            {
                addPlayerButton.Location = buttonPos;
                if (!this.PlayerDetailBox.Visible)
                {
                    addPlayerButton.Image = ResizeImage(ShelSystemViewer.Properties.Resources.new_helmet, (int)((float)buttonLargeDim.X * buttonImageRatio), (int)((float)buttonLargeDim.Y * buttonImageRatio));
                    addPlayerButton.Width = buttonLargeDim.X;
                    addPlayerButton.Height = buttonLargeDim.Y;
                    addPlayerButton.Font = new Font("Microsoft Sans Serif", 13.0F, FontStyle.Regular, GraphicsUnit.Point, ((byte)(0)));
                }
                else
                {
                    addPlayerButton.Image = ResizeImage(ShelSystemViewer.Properties.Resources.new_helmet, (int)((float)buttonSmallDim.X * buttonImageRatio), (int)((float)buttonSmallDim.Y * buttonImageRatio));
                    addPlayerButton.Width = buttonSmallDim.X;
                    addPlayerButton.Height = buttonSmallDim.Y;
                    addPlayerButton.Font = new Font("Microsoft Sans Serif", 7.0F, FontStyle.Regular, GraphicsUnit.Point, ((byte)(0)));
                }
                addPlayerButton.Visible = true;
            }

            // Dependant on player detail box
            if (PlayerDetailBox.Visible)
            {
                labelGameTime.Location = new Point(Size.Width - PlayerDetailBox.Size.Width - labelGameTime.Size.Width - 10,
                                                                       panelTopBar.Height / 2 - labelGameTime.Size.Height / 2);
            }
            else
            {
                labelGameTime.Location = new Point(Size.Width - labelGameTime.Size.Width - 10,
                                                                       panelTopBar.Height / 2 - labelGameTime.Size.Height / 2);
            }
        }

        // Reset the layout of the components in the Player Detail Box section
        private void ResetPlayerDetailBoxComponents(int xOffset, int yOffset)
        {
            PlayerDetailBox.Location = new Point(
                            Size.Width / 3, 0);
            PlayerDetailBox.Size = new Size(
                2 * Size.Width / 3 - 10, Size.Height - 50);
            
            HideButton.Location = new Point(
                PlayerDetailBox.Width - HideButton.Width - 15,
                PlayerDetailBox.Location.Y + 12);
            EditButton.Location = new Point(
                PlayerDetailBox.Width - EditButton.Width - 15,
                HideButton.Location.Y + EditButton.Height + 15);
            RefreshBtn.Location = new Point(
                PlayerDetailBox.Width - RefreshBtn.Width - 15,
                EditButton.Location.Y + RefreshBtn.Height + 15);

            NameLabel.Size = new Size(
                (PlayerDetailBox.Width - xOffset) / 2, yOffset);
            AddressLabel.Size = NameLabel.Size;
            PhoneLabel.Size = NameLabel.Size;
            DobLabel.Size = NameLabel.Size;
            HeightLabel.Size = NameLabel.Size;
            WeightLabel.Size = NameLabel.Size;
            ParentNamesLabel.Size = NameLabel.Size;
            ParentPhoneLabel.Size = NameLabel.Size;
            ParentAltPhoneLabel.Size = NameLabel.Size;
            DocNameLabel.Size = NameLabel.Size;
            DocPhoneLabel.Size = NameLabel.Size;
            // column 1
            NameLabel.Location = new Point(xOffset / 2, yOffset);
            AddressLabel.Location = new Point(xOffset / 2, yOffset * 2);
            PhoneLabel.Location = new Point(xOffset / 2, yOffset * 3);
            DocNameLabel.Location = new Point(xOffset / 2, yOffset * 5);
            DocPhoneLabel.Location = new Point(xOffset / 2, yOffset * 6);
            // column 2
            DobLabel.Location = new Point(
                xOffset / 2 + PlayerDetailBox.Width / 2, yOffset);
            HeightLabel.Location = new Point(
                xOffset / 2 + PlayerDetailBox.Width / 2, yOffset * 2);
            WeightLabel.Location = new Point(
                xOffset / 2 + PlayerDetailBox.Width / 2, yOffset * 3);
            ParentNamesLabel.Location = new Point(
                xOffset / 2 + PlayerDetailBox.Width / 2, yOffset * 4);
            ParentPhoneLabel.Location = new Point(
                xOffset / 2 + PlayerDetailBox.Width / 2, yOffset * 5);
            ParentAltPhoneLabel.Location = new Point(
                xOffset / 2 + PlayerDetailBox.Width / 2, yOffset * 6);

            ResetDoctorNotesComponents(xOffset, yOffset);
            ResetMedicalHistoryComponents();
        }

        // Reset the layout of the components in the Medical History section - column 1
        private void ResetMedicalHistoryComponents()
        {
            MedHistoryBox.Size = DocNotesBox.Size;
            MedHistoryBox.Location = new Point(
               PlayerDetailBox.Width / 2,
               DocNotesBox.Location.Y);
            MedHistoryText.Size = DocNotesText.Size;
            MedHistoryText.Location = new Point(10, 25);
        }

        // Reset the layout of the components in the Doctor Notes section - column 2
        private void ResetDoctorNotesComponents(int xOffset, int yOffset)
        {
            DocNotesBox.Size = new Size(
               (PlayerDetailBox.Width - xOffset) / 2 - 10,
               (PlayerDetailBox.Height - DocPhoneLabel.Location.Y) / 5);
            DocNotesBox.Location = new Point(5, yOffset * 7);
            DocNotesText.Size = new Size
                (DocNotesBox.Width - 20, DocNotesBox.Height - 27);
            DocNotesText.Location = new Point(10, 25);
        }

        /// <summary>
        /// Resize the image to the specified width and height.
        /// </summary>
        /// <param name="image">The image to resize.</param>
        /// <param name="width">The width to resize to.</param>
        /// <param name="height">The height to resize to.</param>
        /// <returns>The resized image.</returns>
        public static Bitmap ResizeImage(Image image, int width, int height)
        {
            //a holder for the result
            Bitmap result = new Bitmap(width, height);

            //use a graphics object to draw the resized image into the bitmap
            using (Graphics graphics = Graphics.FromImage(result))
            {
                //set the resize quality modes to high quality
                graphics.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
                graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
                graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
                //draw the image into the target bitmap
                graphics.DrawImage(image, 0, 0, result.Width, result.Height);
            }

            //return the resulting bitmap
            return result;
        }

        // Background worker DO WORK method
        private void BackgroundWorker_RetrieveMainScreenData(object sender, DoWorkEventArgs e)
        {
            List<Player> tempPlayerList = new List<Player>();
            List<List<Statistics>> tempStatList = new List<List<Statistics>>();

            try
            {
                tempPlayerList = GetListOfPlayers();

                foreach (Player p in tempPlayerList)
                {
                    // Pull history information for every player
                    var client = new HttpClient();
                    var query = ConfigurationManager.AppSettings[WebServiceUrlKey] + "/api/v1/player/" + p.SensorId + "/history/1";
                    var rawResult = client.Get(query).Content.ReadAsString();
                    try
                    {
                        var playerStats = (List<Statistics>)JsonConvert.DeserializeObject(rawResult, typeof(List<Statistics>));
                        tempStatList.Add(playerStats);
                    }
                    catch (SystemException exception)
                    {
                        Console.WriteLine("Error when parsing player history from API: " + exception.Message);
                    }
                }
            }
            catch (SystemException exception)
            {
                Console.WriteLine("Error: " + exception.Message);
            }

            e.Result = Tuple.Create<List<Player>, List<List<Statistics>>>(tempPlayerList, tempStatList);
        }

        // Retrieve current list of players from API
        public static List<Player> GetListOfPlayers()
        {
            List<Player> players = new List<Player>();
            var client = new HttpClient();
            var query = ConfigurationManager.AppSettings[WebServiceUrlKey] + "/api/v1/player/";
            var rawResult = client.Get(query).Content.ReadAsString();
            try
            {
                players = (List<Player>)JsonConvert.DeserializeObject(rawResult, typeof(List<Player>));
            }
            catch (SystemException exception)
            {
                Console.WriteLine("Error when parsing list of players from API: " + exception.Message);
            }

            return players;
        }

        // Background worker WORK DONE method
        private void BackgroundWorker_UpdateMainScreen(object sender, RunWorkerCompletedEventArgs e)
        {
            try
            {
                lock (players)
                {
                    Tuple<List<Player>, List<List<Statistics>>> res = e.Result as Tuple<List<Player>, List<List<Statistics>>>;
                    players = res.Item1;
                    List<List<Statistics>> playerStats = res.Item2;

                    lock (playerButtonLock)
                    {
                        // Check for changes in player list from displayed buttons
                        for (int i = 0; i < players.Count(); ++i)
                        {
                            // Add a new button for this player
                            if (i > playerButtons.Count() - 1)
                            {
                                CreatePlayerButton(players.ElementAt(i));
                                Controls.Add(playerButtons.Last());
                            }
                        }

                        // Check for too many buttons
                        while (playerButtons.Count() > players.Count())
                        {
                            Controls.Remove(playerButtons.Last());
                            playerButtons.Remove(playerButtons.Last());
                        }

                        var worstPlayerStatus = Status.Inactive;

                        // Initialize all helmet icons to grey and fix any numbers that may have changed
                        for (int i = 0; i < playerButtons.Count(); ++i)
                        {
                            if (playerButtons.ElementAt(i).Name != "PlayerIcon" + players.ElementAt(i).SensorId.ToString())
                            {
                                playerButtons.ElementAt(i).Name = "PlayerIcon" + players.ElementAt(i).SensorId.ToString();
                            }

                            if (playerButtons.ElementAt(i).Text != "#" + players.ElementAt(i).UniformNum.ToString())
                            {
                                playerButtons.ElementAt(i).Text = "#" + players.ElementAt(i).UniformNum.ToString();
                            }

                            // color helmet based on current status of player
                            if (playerStats.ElementAt(i) != null && playerStats.ElementAt(i).Count > 0
                                && playerStats.ElementAt(i)[0].DataDateTime.Date.Equals(Today.Date))
                            {
                                switch (playerStats.ElementAt(i)[0].PlayerStatus)
                                {
                                    case Status.Emergency:
                                        playerButtons.ElementAt(i).Image = ShelSystemViewer.Properties.Resources.red_helmet;
                                        if (worstPlayerStatus < Status.Emergency)
                                        {
                                            worstPlayerStatus = Status.Emergency;
                                        }
                                        break;
                                    case Status.Warning:
                                        playerButtons.ElementAt(i).Image = ShelSystemViewer.Properties.Resources.yellow_helmet;
                                        if (worstPlayerStatus < Status.Warning)
                                        {
                                            worstPlayerStatus = Status.Warning;
                                        }
                                        break;
                                    case Status.Good:
                                        playerButtons.ElementAt(i).Image = ShelSystemViewer.Properties.Resources.green_helmet;
                                        if (worstPlayerStatus < Status.Good)
                                        {
                                            worstPlayerStatus = Status.Good;
                                        }
                                        break;
                                    default:
                                        playerButtons.ElementAt(i).Image = ShelSystemViewer.Properties.Resources.grey_helmet;
                                        break;
                                }
                            }
                            else
                            {
                                playerButtons.ElementAt(i).Image = ShelSystemViewer.Properties.Resources.grey_helmet;
                            }
                        }

                        // Reset color of top panel banner to be worst of the players' statuses
                        switch((Status)worstPlayerStatus)
                        {
                            case Status.Emergency:
                                panelTopBar.BackColor = Color.Red;
                                break;
                            case Status.Warning:
                                panelTopBar.BackColor = Color.Yellow;
                                break;
                            case Status.Good:
                                panelTopBar.BackColor = Color.Lime;
                                break;
                            default:
                                panelTopBar.BackColor = Color.Gray;
                                break;
                        }
                    }
                }

                // Reset the display to resize and position the new icons
                ResetMainComponents();
            }
            catch (SystemException exception)
            {
                Console.WriteLine("Error: " + exception.Message);
            }

            // Run again
            backgroundWorker.RunWorkerAsync();
        }

        // Shows the new player form
        private void DisplayNewPlayerForm(object sender, EventArgs e)
        {
            if (playerUpdateForm.IsDisposed)
            {
                playerUpdateForm = new PlayerUpdateForm(ConfigurationManager.AppSettings[WebServiceUrlKey]);
            }
            playerUpdateForm.SetUpdateFormType(true);
            playerUpdateForm.Show();
        }

        // Send text message to doctor
        private void SendDoctorTextMessage(object sender, EventArgs e)
        {
            // error...no doctor exists for this player
            if (DoctorInfo == null)
            {
                MessageBox.Show(
                    "Cannot notify doctor because this player does not currently have a doctor on record.",
                    "Error", MessageBoxButtons.OK);
            }
            // error...no phone # on record for this player
            else if (DoctorInfo.PhoneNumber.Equals(String.Empty))
            {
                MessageBox.Show(
                    "Cannot notify doctor because this doctor does not currently have a phone # on record.",
                    "Error", MessageBoxButtons.OK);
            }
            // success...doc on record with a phone #
            else
            {
                try
                {
                    // instantiate a new Twilio Rest Client    
                    var client = new TwilioRestClient(SmsAccountSid, SmsAccountNumberAuthToken);     
                    // Send a new outgoinging SMS by POSTing to the SMS resource 
                    var response = client.SendSmsMessage(
                        SmsAccountPhoneNumber,          // from           
                        "+1 " + DoctorInfo.PhoneNumber, // to                     
                        String.Format(
                            "#{0} - {1} {2} may need medical attention. Please evaluate at your earliest convenience.",
                            CurrPlayer.UniformNum, CurrPlayer.FirstName,
                            CurrPlayer.LastName)        // body
                        );

                    // Check if text was sent successfully
                    if (response.Status.Equals("queued"))
                    {
                        MessageBox.Show("Text successfully sent to Dr. " + DoctorInfo.LastName + ".",
                            "Text Sent", MessageBoxButtons.OK);
                    }
                    else
                    {
                        MessageBox.Show("Error while trying to notify Dr. " + DoctorInfo.LastName + ".");
                    }
                }
                catch (System.Exception exception)
                {
                    Console.WriteLine("Error: " + exception.Message);
                    MessageBox.Show("Error while trying to notify Dr. " + DoctorInfo.LastName + ".");
                }
            }
        }
    }
}
